<template>
  <div class="vk-from">
    <slot></slot>
  </div>
</template>

<script setup lang="ts">
import { defineProps, defineOptions, provide, defineExpose } from "vue";
import {
  FormProps,
  formContextKey,
  FormItemContext,
  FormContext,
  FormValidateFailure,
  FormInstance,
} from "./types";
import { ValidateFieldsError } from "async-validator";
defineOptions({
  name: "VkForm",
});

const props = defineProps<FormProps>();

const fields: FormItemContext[] = [];
const addField: FormContext["addField"] = (field: FormItemContext) => {
  if (field.prop) {
    fields.push(field);
  }
};
const removeField: FormContext["removeField"] = (field: FormItemContext) => {
  const index = fields.indexOf(field);
  if (index !== -1) {
    fields.splice(index, 1);
  }
};
provide(formContextKey, {
  ...props,
  addField,
  removeField,
});

// 可以传指定的键值，重置对应的表单项
const resetFields = (keys: string[] = []) => {
  const filterArr =
    keys.length > 0
      ? fields.filter((item) => keys.includes(item.prop))
      : fields;
  for (const field of filterArr) {
    field.resetField();
  }
};

// 清空校验
const clearValidate = (keys: string[] = []) => {
  const filterArr =
    keys.length > 0
      ? fields.filter((item) => keys.includes(item.prop))
      : fields;
  for (const field of filterArr) {
    field.clearValidate();
  }
};

const validate = async () => {
  let validationError: ValidateFieldsError = {};
  // Promise.allSettled() 会等待所有的promise都执行完毕，不管成功还是失败
  for (const field of fields) {
    try {
      await field.validate();
    } catch (e: any) {
      const error = e as FormValidateFailure;
      validationError = {
        ...validationError,
        ...error.fields,
      };
    }
  }

  if (Object.keys(validationError).length === 0) {
    return true;
  } else {
    Promise.reject(validationError);
  }
};
defineExpose<FormInstance>({
  validate,
  resetFields,
  clearValidate,
});
</script>

<style scoped></style>
